package com.cmas.platform.service.impl;

import com.aidex.common.annotation.DataSource;
import com.aidex.common.enums.DataSourceType;
import com.aidex.common.utils.SecurityUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmas.platform.domain.*;
import com.cmas.platform.domain.em.UserLikeTypeEnum;
import com.cmas.platform.dto.CommentDto;
import com.cmas.platform.mapper.CommentFullMapper;
import com.cmas.platform.service.*;
import com.cmas.platform.utils.DataRedisUtil;
import com.cmas.platform.vo.CommentVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * @Author su
 * @Date 2023/5/11 1:15
 */
@Service
public class CommentFullServiceImpl extends ServiceImpl<CommentFullMapper, CommentDto> implements CommentFullService {
    private static final Logger log = LoggerFactory.getLogger(CommentFullServiceImpl.class);

    @Autowired
    private CommentService commentService;
    @Autowired
    private RegionService regionService;
    @Autowired
    private SectionService sectionService;
    @Autowired
    private PostService postService;
    @Autowired
    private UserLikeService userLikeService;

    @Autowired
    private DataRedisUtil dataRedisUtil;


    @DataSource(value = DataSourceType.SLAVE)
    @Override
    public IPage<CommentDto> selectCommentFullDto(Integer current, Integer size, Comment comment) {
        Page<CommentDto> page = new Page<>(current, size);
        QueryWrapper<Comment> commentQueryWrapper = setQueryWrapper(comment);
        commentQueryWrapper.lambda().isNull(Comment::getPid);
        List<CommentDto> commentDtoList = baseMapper.selectCommentDtoList(setCurrent(current, size),
                setSize(current, size), commentQueryWrapper);
        String userId = SecurityUtils.getUserId();
        List<UserLike> userLikeList = userLikeService
                .list(new QueryWrapper<UserLike>().lambda().eq(UserLike::getUserId, userId).
                        eq(UserLike::getType, UserLikeTypeEnum.COMMENT.getValue()).eq(UserLike::getIsLike, "1"));
        List<CommentDto> commentTree = getChildList(comment, commentDtoList, userLikeList);
        //手动排序
        commentTree.sort(Comparator.comparing(CommentDto::getCreateTime));
        page.setRecords(commentTree);
        return page;
    }

    @Async
    @DataSource(value = DataSourceType.SLAVE)
    @Override
    public void reloadRedisPost(String postId) {
        Post post = postService.getById(postId);
        Region region = regionService.getById(post.getRegionId());
        Section section = sectionService.getById(post.getSectionId());
        dataRedisUtil.addRedisPost(region.getCode(), section.getCode(), postId);
    }


    private List<CommentDto> getChildList(Comment comment, List<CommentDto> commentDtoList, List<UserLike> userLikeList) {
        List<CommentDto> commentDtoAllList = baseMapper.selectCommentDtoList(0, Integer.MAX_VALUE, setQueryWrapper(comment));
        List<CommentDto> treeList = getTreeList(new ArrayList<>(), commentDtoAllList, userLikeList,null);
        List<CommentDto> result = new ArrayList<>();
        for (CommentDto commentDto : commentDtoList) {
            for (CommentDto dto : treeList) {
                if (dto.getId().equals(commentDto.getId())) {
                    result.add(dto);
                }
            }
        }
        return result;
    }

    private List<CommentDto> getTreeList(List<CommentDto> commentDtoTreeList, List<CommentDto> commentDtoList,
                                         List<UserLike> userLikeList, CommentDto temp) {
        for (CommentDto commentDto : commentDtoList) {
            for (UserLike like : userLikeList) {
                //是否点赞
                if (like.getItemId().equals(commentDto.getId())) {
                    commentDto.setIsLike(true);
                }
            }
            String parentId = commentDto.getPid();
            CommentDto tree = new CommentDto();
            BeanUtils.copyProperties(commentDto, tree);
            if (temp == null && StringUtils.isEmpty(parentId)) {
                commentDtoTreeList.add(tree);
                getTreeList(commentDtoTreeList, commentDtoList,userLikeList, tree);
            } else if (temp != null && parentId != null && parentId.equals(temp.getId())) {
                temp.getChildList().add(tree);
                getTreeList(commentDtoTreeList, commentDtoList, userLikeList,tree);

            }
        }
        return commentDtoTreeList;
    }


    private List<CommentDto> getTreeList(List<CommentDto> commentDtoTreeList, List<CommentDto> commentDtoList, CommentDto temp) {
        for (CommentDto commentDto : commentDtoList) {
            String parentId = commentDto.getPid();
            CommentDto tree = new CommentDto();
            BeanUtils.copyProperties(commentDto, tree);
            if (temp == null && StringUtils.isEmpty(parentId)) {
                commentDtoTreeList.add(tree);
                getTreeList(commentDtoTreeList, commentDtoList, tree);
            } else if (temp != null && parentId != null && parentId.equals(temp.getId())) {
                temp.getChildList().add(tree);
                getTreeList(commentDtoTreeList, commentDtoList, tree);

            }
        }
        return commentDtoTreeList;
    }

    private QueryWrapper<Comment> setQueryWrapper(Comment comment) {
        CommentVo commentVo = new CommentVo();
        BeanUtils.copyProperties(comment, commentVo);
        commentVo.setStatus("1,4");
        return commentService.setQueryWrapper(commentVo);
    }

    private Integer setCurrent(Integer current, Integer size) {
        int start = 0;
        if (current > 1) {
            start = current * size - size;
        }
        return start;
    }

    private Integer setSize(Integer current, Integer size) {
        return current * size;
    }

}
